package com.easy.common.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ReflectUtility {

	private static Map<String, Object> primClassMap;

	public ReflectUtility()
	{
	}
	public static Iterator<?> itObject(Object obj, String fieldName)
	throws Exception
	{
		String methodName = (new StringBuilder("it")).append(fieldName.substring(0, 1).toUpperCase()).append(fieldName.substring(1)).toString();
		return (Iterator<?>)exeMethod(obj, methodName, new Class[0], new Object[0]);
	}
	
	public static Object getValue(Object obj, String fieldName)
		throws Exception
	{
		String methodName = (new StringBuilder("get")).append(fieldName.substring(0, 1).toUpperCase()).append(fieldName.substring(1)).toString();
		return exeMethod(obj, methodName, new Class[0], new Object[0]);
	}
	
	public static boolean addObj(Object parentObj, Object detlObj, String fieldName)
		throws Exception
	{
		String methodName = null;
		String tmpStr = null;
		if (fieldName.endsWith("List"))
			tmpStr = fieldName.substring(0, fieldName.length() - 4);
		else
		if (fieldName.endsWith("Map"))
			tmpStr = fieldName.substring(0, fieldName.length() - 3);
		else
			return false;
		methodName = (new StringBuilder("add")).append(tmpStr.substring(0, 1).toUpperCase()).append(tmpStr.substring(1)).toString();
		exeMethod(parentObj, methodName, new Class[] {
			detlObj.getClass()
		}, new Object[] {
			detlObj
		});
		return true;
	}
	
	public static boolean setValue(Object obj, String fieldName, Class<?> fieldType, String fieldValue)
		throws Exception
	{
		String methodName = (new StringBuilder("set")).append(fieldName.substring(0, 1).toUpperCase()).append(fieldName.substring(1)).toString();
		if (fieldType.equals(Integer.TYPE))
			if (Utility.isNullorEmpty(fieldValue))
			{
				return false;
			} else
			{
				fieldValue = fieldValue.trim();
				exeMethod(obj, methodName, new Class[] {
					Integer.TYPE
				}, new Object[] {
					new Integer(fieldValue)
				});
				return true;
			}
		if (fieldType.equals(Integer.class))
			if (Utility.isNullorEmpty(fieldValue))
			{
				return false;
			} else
			{
				fieldValue = fieldValue.trim();
				exeMethod(obj, methodName, new Class[] {
					Integer.class
				}, new Object[] {
					new Integer(fieldValue)
				});
				return true;
			}
		if (fieldType.equals(Long.TYPE))
			if (Utility.isNullorEmpty(fieldValue))
			{
				return false;
			} else
			{
				fieldValue = fieldValue.trim();
				exeMethod(obj, methodName, new Class[] {
					Long.TYPE
				}, new Object[] {
					new Long(fieldValue)
				});
				return true;
			}
		if (fieldType.equals(Long.class))
			if (Utility.isNullorEmpty(fieldValue))
			{
				return false;
			} else
			{
				fieldValue = fieldValue.trim();
				exeMethod(obj, methodName, new Class[] {
					Long.class
				}, new Object[] {
					new Long(fieldValue)
				});
				return true;
			}
		if (fieldType.equals(Double.TYPE))
			if (Utility.isNullorEmpty(fieldValue))
			{
				return false;
			} else
			{
				fieldValue = fieldValue.trim();
				exeMethod(obj, methodName, new Class[] {
					Double.TYPE
				}, new Object[] {
					new Double(fieldValue)
				});
				return true;
			}
		if (fieldType.equals(Double.class))
			if (Utility.isNullorEmpty(fieldValue))
			{
				return false;
			} else
			{
				fieldValue = fieldValue.trim();
				exeMethod(obj, methodName, new Class[] {
					Double.class
				}, new Object[] {
					new Double(fieldValue)
				});
				return true;
			}
		if (fieldType.equals(String.class))
		{
			exeMethod(obj, methodName, new Class[] {
				String.class
			}, new Object[] {
				fieldValue
			});
			return true;
		}
		if (fieldType.equals(java.util.Date.class))
		{
			exeMethod(obj, methodName, new Class[] {
				java.util.Date.class
			}, new Object[] {
				Utility.parseDate(fieldValue)
			});
			return true;
		}
		if (fieldType.equals(java.sql.Date.class))
		{
			exeMethod(obj, methodName, new Class[] {
				java.sql.Date.class
			}, new Object[] {
				Utility.parseSqlDate(fieldValue)
			});
			return true;
		}
		if (fieldType.equals(Boolean.TYPE))
		{
			exeMethod(obj, methodName, new Class[] {
				Boolean.TYPE
			}, new Object[] {
				Boolean.valueOf(fieldValue)
			});
			return true;
		}
		if (fieldType.equals(Boolean.class))
		{
			exeMethod(obj, methodName, new Class[] {
				Boolean.class
			}, new Object[] {
				Boolean.valueOf(fieldValue)
			});
			return true;
		} else
		{
			return false;
		}
	}
	
	public static Object exeMethod(String className, String method, String paramTypeNameArray[], Object params[])
		throws Exception
	{
		Object classObj;
		Method methodObj;
		try{
			Class<?> classDef = Class.forName(className);
			Class<?> paramTypeArray[] = (Class[])null;
			if (paramTypeNameArray == null)
			{
				paramTypeArray = new Class[0];
			} else
			{
				paramTypeArray = new Class[paramTypeNameArray.length];
				for (int i = 0; i < paramTypeNameArray.length; i++)
				{
					String typeName = paramTypeNameArray[i];
					if (primClassMap.containsKey(typeName))
						paramTypeArray[i] = (Class<?>)primClassMap.get(typeName);
					else
						paramTypeArray[i] = Class.forName(typeName);
				}
		
			}
			classObj = classDef.newInstance();
			methodObj = classDef.getMethod(method, paramTypeArray);
			return methodObj.invoke(classObj, params);
		}
		catch(Exception e){
			throw e;
		}
	}
	// 把一个字符串的第一个字母大写、效率是最高的、  
	private static String getMethodName(String fildeName) {  
		byte[] items = fildeName.getBytes();  
		items[0] = (byte) ((char) items[0] - 'a' + 'A');  
		return new String(items);  
	}  

	/**
	 * 通过java的反射机制复制对象
	 * @param targetClassObj 目标对象
	 * @param sourceClassObj 原对象
	 * @return 
	 * @throws Exception 
	 */
	public static Object copyMethod(Object targetClassObj,Object sourceClassObj) throws Exception
	{
		if (targetClassObj== null) return null;
		Field[] tFields = targetClassObj.getClass().getDeclaredFields();
		Field[] sFields = sourceClassObj.getClass().getDeclaredFields();
        try {
            for (Field field : tFields ) {
                String fieldName = field.getName();
                if (fieldName.equals("serialVersionUID")) continue;
                if (field.getType() == Map.class) continue;

                if (field.getType() == Set.class) continue;

                if (field.getType() == List.class) continue;
                for (Field sField : sFields) {
                    if(!sField .getName().equals(fieldName)){
                        continue;
                    }
                    Class<?> type = field.getType();
                    String setName = "set"+getMethodName(fieldName);
                    Method tMethod = targetClassObj.getClass().getMethod(setName, new Class[]{type});
                    String getName = "get"+getMethodName(fieldName);
                    Method sMethod = sourceClassObj.getClass().getMethod(getName, null);
                    Object setterValue = sMethod.invoke(sourceClassObj, null);
                    tMethod.invoke(targetClassObj, new Object[]{setterValue});
                }
            }
        } catch (Exception e) {
            throw new Exception("设置参数信息发生异常", e);
        }
        return targetClassObj;
	}
	public static Object exeMethod(Object classObj, String method, Class<?> paramTypeArray[], Object params[])
		throws Exception
	{
		try{
			Class<?> classDef = classObj.getClass();
			Method methodObj = classDef.getMethod(method, paramTypeArray);
			return methodObj.invoke(classObj, params);
		}
		catch(Exception e){
			throw e;
		}
	}
	static 
	{
		primClassMap = new HashMap<String, Object>();
		primClassMap.put("byte", Byte.TYPE);
		primClassMap.put("short", Short.TYPE);
		primClassMap.put("int", Integer.TYPE);
		primClassMap.put("long", Long.TYPE);
		primClassMap.put("float", Float.TYPE);
		primClassMap.put("double", Double.TYPE);
		primClassMap.put("boolean", Boolean.TYPE);
		primClassMap.put("char", Character.TYPE);
	}
}
